package com.rapida.framwork;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class Signal {
	private HashMap<Slot, List<Method>> m_connected_slots = new HashMap<Slot, List<Method>>();

	public void connect(Slot slot) {
		registerSlots(slot);
		slot.signal_connect(this);
	}

	public void disconnect(Slot slot) {
		Iterator<Slot> iter = m_connected_slots.keySet().iterator();
		while (iter.hasNext()) {
			iter = m_connected_slots.keySet().iterator();
			Slot key = (Slot) iter.next();
			if (slot == key) {
				m_connected_slots.remove(key);
			}
		}
		slot.signal_disconnect(this);
	}

	private void registerSlots(Slot slot) {
		Method[] methods = slot.getClass().getDeclaredMethods();
		if (methods != null && methods.length > 0) {
			for (Method method : methods) {
				try {
					method.setAccessible(true);
					ISlots st = method.getAnnotation(ISlots.class);
					if (st != null && st.connect()
							&& method.getName().equals(st.name())) {
						if (m_connected_slots.get(slot) != null) {
							m_connected_slots.get(slot).add(method);
						} else {
							List<Method> list = new ArrayList<Method>();
							list.add(method);
							m_connected_slots.put(slot, list);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void emit(String name, Object... values) {
		Iterator<Slot> iter = m_connected_slots.keySet().iterator();
		while (iter.hasNext()) {
			Slot key = (Slot) iter.next();
			try {
				for (Method method : m_connected_slots.get(key)) {
					if (method.getName().equals(name)) {
						method.invoke(key, values);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
